package com.palominocia.capa_datos_nodoCentral.dbPostgreSQL.schema1.controles;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;

import javax.activation.DataHandler;
import javax.persistence.EntityManager;
import javax.persistence.Query;

import org.apache.log4j.Logger;

import com.palominocia.capa_datos_nodoCentral.dbPostgreSQL.schema1.modelo.opciones.Habilitacion;
import com.palominocia.capa_datos_nodoCentral.dbPostgreSQL.schema1.modelo.opciones.Opciones;
import com.palominocia.capa_datos_nodoCentral.dbPostgreSQL.schema1.modelo.opciones.OpcionesPerfil;
import com.palominocia.capa_datos_nodoCentral.dbPostgreSQL.schema1.modelo.opciones.ParametrosRespuesta;
import com.palominocia.capa_datos_nodoCentral.dbPostgreSQL.schema1.modelo.seguridad.Sesiones;
import com.palominocia.capa_datos_nodoCentral.dbPostgreSQL.schema1.modelo.seguridad.TipoAcceso;
import com.palominocia.capa_datos_nodoCentral.dbPostgreSQL.schema1.modelo.seguridad.Usuario;
import com.palominocia.capa_datos_nodoCentral.dbPostgreSQL.schema1.servicios.entrada.ParametrosEnvio;
import com.palominocia.capa_datos_nodoCentral.dbPostgreSQL.schema1.servicios.salida.NodosArbol;
import com.palominocia.capa_datos_nodoCentral.dbPostgreSQL.schema1.util.Constantes;
import com.palominocia.capa_datos_nodoCentral.dbPostgreSQL.schema1.util.SendEmail;
import com.palominocia.capa_datos_nodoCentral.dbPostgreSQL.schema1.util.UtilRandom;
import com.palominocia.capa_datos_nodoCentral.dbPostgreSQL.schema1.util.Utiles;

public class ControlNodoCentral {

	private static ControlNodoCentral instancia;
	private static Logger logger = Logger.getLogger(ControlNodoCentral.class);
	private ParametrosRespuesta param;
	public static synchronized ControlNodoCentral getInstance() {
		if (instancia == null) {
			instancia = new ControlNodoCentral();
		}
		return instancia;
	}
	public HashMap<String, Object> ejecutaconsulta(String nombreUsuario, String metodoRemoto) {
		HashMap<String, Object> msgRespuesta = new HashMap<String, Object>();	
		logger.info("Inicio ejecutaconsulta");
		try {
			//Verifica los perfiles
			Opciones opciones =null;
			OpcionesPerfil opPerfil=null;
			Usuario user=null;
			
			opciones=Opciones.findOpcionesbyNombreOpcion(metodoRemoto);
			user=Usuario.findNombreUsuario(nombreUsuario);
			if(opciones instanceof Opciones){
				//El user ya fue autentificado en el filter
				opPerfil=OpcionesPerfil.findOpcionPerfil(opciones,user);
				if(opPerfil instanceof OpcionesPerfil){
					ArrayList<Object> lista =null;
					lista=procesaQuery(opciones.getTxtDatosAdicionales());
					param =Utiles.CalculaParametro(0);
					msgRespuesta.put("query_salida", lista);
				}
				else{
					//No existe opcion-perfil
					param =Utiles.CalculaParametro(27);
				}
			}
			else{
				param =Utiles.CalculaParametro(26);
				//No existe opcion
			}
			msgRespuesta.put("codigo", param.getCodigoParametroRespuesta());
			msgRespuesta.put("mensaje", param.getNombreParametroRespuesta());
			logger.info("Fin ejecutaconsulta");
		} catch (Exception e) {
			logger.error("Error ejecutaconsulta",e);
			param =Utiles.CalculaParametro(999999);
			msgRespuesta.put("codigo", param.getCodigoParametroRespuesta());
			msgRespuesta.put("mensaje", param.getNombreParametroRespuesta()+e.getMessage());
		}
		
		return msgRespuesta;
	}
	private ArrayList<Object> procesaQuery(String txtDatosAdicionales) {
		List<Object> lista = new ArrayList();

		EntityManager em = Opciones.entityManager();
		try {
			Query q =em.createNativeQuery(txtDatosAdicionales);
			lista=q.getResultList();
			//q.setParameter( 1, "" );
		} catch (Exception e) {
			logger.error("ERROR en procesaQuery", e);
			//e.printStackTrace();
			lista=null;
		}
		return (ArrayList<Object>) lista;
	}
	public HashMap<String, Object> validarUsuario(String ipAdress,Long tipo_acceso, String username, String tokenReferencia) {
		HashMap<String, Object> msgRespuesta = new HashMap<String, Object>();	
		logger.info("Inicio validarUsuario");
		if(Utiles.validaDireccionIp(ipAdress)){
			try {
				String token_user="";
				Calendar cal = Calendar.getInstance();
				Sesiones ses =null;
				TipoAcceso tipo =TipoAcceso.findTipoAcceso(tipo_acceso.longValue());
				Usuario user =Usuario.findNombreUsuario(username);
				if(user instanceof Usuario){
					if(tipo instanceof TipoAcceso){
						//Buscamos el token recibido en caso no exista se genera uno nuevo
						ses=Sesiones.findSesionesbyToken(tokenReferencia);
						if(ses instanceof Sesiones){
							logger.info("ses.getIpAdressSesion(): "+ses.getIpAdressSesion());
							logger.info("ipAdress: "+ipAdress);
							
							ses.setSesionValida(Habilitacion.HABILITADO);
							ses.setIpAdressSesion(ipAdress);
							ses.setTokenReferencia(tokenReferencia);
							ses.setFechaIniSesion(cal.getTime());
							ses.setTipoAccesoSesion(tipo);
							ses.setUsernameSesion(user);
							ses.merge();
							
							msgRespuesta.put("tokenLogin", tokenReferencia);
						}
						else{
							//Deshabilitar tokens anteriores con la misma ip y dispositivo
							List<Sesiones> sesiones_pendientes =Sesiones.findAllSesionesbyUserAccesoIp(user,tipo,ipAdress);
							for(Sesiones pendi: sesiones_pendientes){
								pendi.setSesionValida(Habilitacion.DESHABILITADO);
								pendi.merge();
							}
							
							token_user=UtilRandom.generarTokenPassword();
							ses = new Sesiones();
							ses.setSesionValida(Habilitacion.HABILITADO);
							ses.setIpAdressSesion(ipAdress);
							ses.setTokenReferencia(token_user);
							ses.setFechaIniSesion(cal.getTime());
							ses.setTipoAccesoSesion(tipo);
							ses.setUsernameSesion(user);
							ses.persist();
							msgRespuesta.put("tokenLogin", token_user);
						}
						param =Utiles.CalculaParametro(0);
						
					}
					else{
						param =Utiles.CalculaParametro(25);
					}
				}
				else{
					param =Utiles.CalculaParametro(2);
				}

				msgRespuesta.put("codigo", param.getCodigoParametroRespuesta());
				msgRespuesta.put("mensaje", param.getNombreParametroRespuesta());
				logger.info("Fin validarUsuario");
			}
			catch(Exception e){
				logger.error("Error validarUsuario",e);
				param =Utiles.CalculaParametro(999999);
				msgRespuesta.put("codigo", param.getCodigoParametroRespuesta());
				msgRespuesta.put("mensaje", param.getNombreParametroRespuesta()+e.getMessage());
			}
		}
		else{
			param =Utiles.CalculaParametro(3);
			msgRespuesta.put("codigo", param.getCodigoParametroRespuesta());
			msgRespuesta.put("mensaje", param.getNombreParametroRespuesta());
		}
		
		return msgRespuesta;
	}


	public HashMap<String, Object> invalidaToken(String tokenReferencia) {
		HashMap<String, Object> msgRespuesta = new HashMap<String, Object>();	
		logger.info("Inicio invalidaToken");
		Sesiones ses =null;
		try {
			ses=Sesiones.findSesionesbyToken(tokenReferencia);
			if(ses instanceof Sesiones){
				ses.setSesionValida(Habilitacion.DESHABILITADO);
				ses.merge();
				param =Utiles.CalculaParametro(0);
			}
			else{
				param =Utiles.CalculaParametro(50);
			}
			logger.info("Fin invalidaToken");
		} catch (Exception e) {
			logger.error("Error invalidaToken",e);
			param =Utiles.CalculaParametro(999999);
			msgRespuesta.put("codigo", param.getCodigoParametroRespuesta());
			msgRespuesta.put("mensaje", param.getNombreParametroRespuesta()+e.getMessage());
		}
		
		return msgRespuesta;
	}
	public HashMap<String, Object> envioCorreo(ParametrosEnvio envioparam,
			String adjuntoB64, DataHandler adjuntoBin, String mensaje) {
		HashMap<String, Object> msgRespuesta = new HashMap<String, Object>();	
		logger.info("Inicio envioCorreo");
		try {
			SendEmail envio =new SendEmail();
			envio.setParametrosEnvio(envioparam);
			envio.setAdjuntoB64(adjuntoB64);
			envio.setDataHandler(adjuntoBin);
			envio.setMensaje(mensaje);
			envio.setTimeout(1000);
			//envio.procesarEnvio();
			envio.enviar();
			logger.info("Fin envioCorreo");
		} catch (Exception e) {
			logger.error("Error envioCorreo",e);
			param =Utiles.CalculaParametro(999999);
			msgRespuesta.put("codigo", param.getCodigoParametroRespuesta());
			msgRespuesta.put("mensaje", param.getNombreParametroRespuesta()+e.getMessage());
		}
		
		/* try {
	         InputStream is = handler.getInputStream();

	         OutputStream os = new FileOutputStream(new File(""));
	         byte[] b = new byte[100000];
	         int bytesRead = 0;
	         while ((bytesRead = is.read(b)) != -1) {
	            os.write(b, 0, bytesRead);
	         }
	         os.flush();
	         os.close();
	         is.close();

	      } catch (IOException e) {
	         e.printStackTrace();
	      }*/
		
		return null;
	}
	public HashMap<String, Object> generaArbol(String codPadre) {
		HashMap<String, Object> msgRespuesta = new HashMap<String, Object>();	
		logger.info("Inicio generaArbol");
		ArrayList<NodosArbol> lista =null;
		try {
			NodosArbol nodoActual = new NodosArbol();
			List<Opciones> options =Opciones.findOpcionesbyCodOpcion(Integer.valueOf(codPadre));
			if(options!=null){
				nodoActual.setCodigoNodo(codPadre);
				nodoActual.setImagenNodo(Constantes.IMAGEN_NODO_PADRE);
				nodoActual.setTipoNodo(Constantes.TIPO_NODO_PADRE);
				lista= new ArrayList<NodosArbol>();
				for(Opciones op :options){
					NodosArbol nodosHijos = new NodosArbol();
					nodosHijos.setNodoPadre(nodoActual);
					nodosHijos.setCodigoNodo(op.getCodOpcion()+"");
					nodosHijos.setNombreNodo(op.getNombreOpcion());
					nodosHijos.setImagenNodo(Constantes.IMAGEN_NODO_HIJO);
					nodosHijos.setTipoNodo(Constantes.TIPO_NODO_HIJO);
					nodosHijos.setUrlEjecutar("");
					lista.add(nodosHijos);
				}
				param =Utiles.CalculaParametro(0);
				msgRespuesta.put("arbol_salida", lista);
			}
			else{
				param =Utiles.CalculaParametro(0);
			}
			
			msgRespuesta.put("codigo", param.getCodigoParametroRespuesta());
			msgRespuesta.put("mensaje", param.getNombreParametroRespuesta());
			
			logger.info("Fin generaArbol");
			
		} catch (Exception e) {
			logger.error("Error generaArbol",e);
			param =Utiles.CalculaParametro(999999);
			msgRespuesta.put("codigo", param.getCodigoParametroRespuesta());
			msgRespuesta.put("mensaje", param.getNombreParametroRespuesta()+e.getMessage());
		}
		return msgRespuesta;
	}

}
